﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using Axelerate.Silverlight3D.Media.Media3D;

namespace VS.Infrastructure.Controls
{
    public class TagPanel : Panel
    {
        #region Fields
        private RotateTransform3D _rotateTransform;
        private bool _runRotation;
        private double _angle;
        double _decrease;
        #endregion

        public TagPanel()
            : base()
        {
            Background = new SolidColorBrush(Colors.Transparent);
            _rotateTransform = new RotateTransform3D();
            _rotateTransform.Rotation = new AxisAngleRotation3D(new Vector3D(1.0, 0.0, 0.0), 0);
            CompositionTarget.Rendering += new EventHandler(CompositionTarget_Rendering);
            MouseEnter += new MouseEventHandler(TagPanel_MouseEnter);
            MouseLeave += new MouseEventHandler(TagPanel_MouseLeave);
            MouseMove += new MouseEventHandler(TagPanel_MouseMove);
        }

        private void TagPanel_MouseMove(object sender, MouseEventArgs e)
        {
            Point mouseLocation = e.GetPosition(this);
            double relativeX = mouseLocation.X - (ActualWidth / 2);
            double relativeY = mouseLocation.Y - (ActualHeight / 2);
            _angle = Math.Sqrt(Math.Pow(relativeX, 2) + Math.Pow(relativeY, 2)) / 25;
            _rotateTransform.Rotation = new AxisAngleRotation3D(new Vector3D(relativeY, relativeX, 0), _angle);
        }

        private void TagPanel_MouseLeave(object sender, MouseEventArgs e)
        {
            MouseMove -= new MouseEventHandler(TagPanel_MouseMove);
            _decrease = 0.1;
        }

        private void TagPanel_MouseEnter(object sender, MouseEventArgs e)
        {
            MouseMove += new MouseEventHandler(TagPanel_MouseMove);
            _decrease = 0;
        }

        private void CompositionTarget_Rendering(object sender, EventArgs e)
        {
            _angle = _angle - (_angle * _decrease);
            _runRotation = _angle >_decrease;

            if (_runRotation)
            {                
                ((AxisAngleRotation3D)_rotateTransform.Rotation).Angle = _angle;
                RotateBlocks();
            }
    
        }

        private void RotateBlocks()
        {
            foreach (TagCloudItem container in Children)
            {
                Point3D newPoint;
                if (_rotateTransform.TryTransform(container._centerPoint, out newPoint))
                {
                    container._centerPoint = newPoint;
                    container.Redraw(ActualWidth / 2, ActualHeight / 2);
                }
            }
        }

        protected override Size ArrangeOverride(Size finalSize)
        {
            double radius = finalSize.Width / 3;
            int max = Children.Count;
            double phi = 0;
            double theta = 0;

            for (int i = 0; i < max; i++)
            {
                phi = Math.Acos(-1.0 + (2.0 * i) / max);
                theta = Math.Sqrt(max * Math.PI) * phi;
                double x = radius * Math.Cos(theta) * Math.Sin(phi);
                double y = radius * Math.Sin(theta) * Math.Sin(phi);
                double z = radius * Math.Cos(phi);

                TagCloudItem tc = Children[i] as TagCloudItem;
                tc._centerPoint.X = x;
                tc._centerPoint.Y = y;
                tc._centerPoint.Z = z;

                tc.Redraw(finalSize.Width / 2, finalSize.Height / 2);
            }

            return finalSize;
        }

        protected override Size MeasureOverride(Size availableSize)
        {

            foreach (TagCloudItem item in Children)
                item.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));

            return base.MeasureOverride(availableSize);
        }
    }
}
